package vip.xiaonuo.visitordevice.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.generator.UUIDGenerator;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.Reactor;
import reactor.event.Event;
import reactor.util.CollectionUtils;
import vip.xiaonuo.core.context.constant.ConstantContextHolder;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.file.FileOperator;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.facedoor.modular.constant.BaseConstant;
import vip.xiaonuo.facedoor.modular.device.listener.DeviceChangeTypeEnum;
import vip.xiaonuo.facedoor.modular.device.listener.DevicePublisher;
import vip.xiaonuo.facedoor.modular.device.listener.DeviceSourceEnum;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.deviceset.constant.DeviceConstant;
import vip.xiaonuo.facedoor.modular.deviceset.entity.DwDeviceSet;
import vip.xiaonuo.facedoor.modular.deviceset.param.DwDeviceSetParam;
import vip.xiaonuo.facedoor.modular.deviceset.service.DwDeviceSetService;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.mapper.MemberUserMapper;
import vip.xiaonuo.facedoor.modular.memberuser.param.MemberUserParam;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.facedoor.modular.memberuser.vo.MemberUserPageVO;
import vip.xiaonuo.facedoor.modular.topic.EventTopic;
import vip.xiaonuo.facedoor.modular.visitor.constant.VisitorConstant;
import vip.xiaonuo.facedoor.modular.visitor.entity.Visitor;
import vip.xiaonuo.facedoor.modular.visitor.service.VisitorService;
import vip.xiaonuo.sys.config.FileConfig;
import vip.xiaonuo.sys.modular.file.entity.SysFileInfo;
import vip.xiaonuo.sys.modular.file.service.SysFileInfoService;
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
import vip.xiaonuo.sys.modular.org.service.SysOrgService;
import vip.xiaonuo.visitordevice.vo.VisitorApiSaveVO;
import vip.xiaonuo.visitordevice.vo.VisitorDeviceCountVO;
import vip.xiaonuo.visitordevice.vo.VisitorQueryVO;

import java.io.File;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class VisitorDeviceApiService {

    @Autowired
    private DeviceBaseService deviceBaseService;

    @Autowired
    private MemberUserService memberUserService;

    @Autowired
    private SysOrgService sysOrgService;

    @Autowired
    private VisitorService visitorService;

    @Autowired
    private Reactor reactor;

    @Autowired
    private FileOperator fileOperator;

    @Autowired
    private DwDeviceSetService dwDeviceSetService;

    @Autowired
    private DevicePublisher devicePublisher;

    @Autowired
    private SysFileInfoService sysFileInfoService;

    @Autowired
    private MemberUserMapper userMapper;

    public Visitor visitorDetail(Long visitorId, String card) {
        if (visitorId != null) {
            return visitorService.getById(visitorId);
        } else {

            List<MemberUser> list = memberUserService.list(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getIcCard, card));
            if (CollectionUtil.isNotEmpty(list)) {
                throw new ServiceException(500, "卡号被内部人员占用!");
            }
            return visitorService.getOne(new LambdaQueryWrapper<Visitor>().eq(Visitor::getSource, 3)
                    .eq(Visitor::getIcCard, card).notIn(Visitor::getStatus, "4", "3", "2")
                    .eq(Visitor::getIssuanceOfVouchers, 0));
        }
    }

    public boolean existsVisitorCard(String card) {
        List<Visitor> list = visitorService.list(new LambdaQueryWrapper<Visitor>().eq(Visitor::getIcCard, card)
                .eq(Visitor::getSource, 3).ne(Visitor::getStatus, 4).eq(Visitor::getIssuanceOfVouchers, 0));
        List<MemberUser> memberUsers = memberUserService.list(new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getIcCard, card));
        return CollectionUtil.isNotEmpty(list) || CollectionUtil.isNotEmpty(memberUsers);
    }

    public Visitor saveAndApproved(VisitorApiSaveVO visitorApiVO) {
        SysOrg visitor_group = sysOrgService.getOne(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getCode, BaseConstant.VISITOR_DEVICE_GROUP));
        if (visitor_group == null) {
            throw new ServiceException(500, "访客组不存在！");
        }
        if (StringUtils.isNotBlank(visitorApiVO.getIcCard()) && existsVisitorCard(visitorApiVO.getIcCard())) {
            throw new ServiceException(500, "卡号被占用！");
        }
        Visitor visitor = new Visitor();
        BeanUtils.copyProperties(visitorApiVO, visitor);
        if (visitorApiVO.getInviterId() != null) {
            MemberUser memberUser = memberUserService.getById(visitorApiVO.getInviterId());
            if (memberUser != null) {
                visitor.setInviterName(memberUser.getName());
            }
        }
        if (visitorApiVO.getCompanyId() != null) {
            SysOrg sysOrg = sysOrgService.getById(visitorApiVO.getCompanyId());
            if (sysOrg != null) {
                visitor.setCompanyName(sysOrg.getName());
            }
        }
        // 3 代表访客机
        visitor.setSource(3);
        visitor.setOrgId(visitor_group.getId());
        visitor.setIssuanceOfVouchers(0);
        visitor.setStatus(VisitorConstant.EXAMINATION_PASSD);
        String fileName = new UUIDGenerator().next().concat(".png");
        visitor.setQrCode(File.separator.concat("qrCode").concat(File.separator).concat(fileName));
        visitorService.save(visitor);
        fileOperator.saveQrCode(FileConfig.DEFAULT_BUCKET.concat(File.separator).concat("qrCode"), fileName, "cfgc_v_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + "_" + visitor.getId());
        // 通知设备做新增访客处理
        reactor.notify(EventTopic.VISITOR_DEVICE_ADD, Event.wrap(visitor.getId()));
        return visitor;
    }

    public Visitor printQrCode(Long visitorId) {
        Visitor visitor = visitorService.getById(visitorId);

        if (visitor==null){
            throw new ServiceException(500,"访客不存在");
        }
        if (!ObjectUtil.equal(visitor.getStatus(), VisitorConstant.EXAMINATION_PASSD)) {
            throw new ServiceException(500, "未通过审批不可打码!");
        }
        String fileName = new UUIDGenerator().next().concat(".png");
      String qrStr=  "cfgc_d_" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + "_" + visitor.getId();
        fileOperator.saveQrCode(FileConfig.DEFAULT_BUCKET.concat(File.separator).concat("qrCode"),
                fileName, qrStr);
        visitor.setQrCode(File.separator.concat("qrCode").concat(File.separator).concat(fileName));
        visitor.setIssuanceOfVouchers(0);
        visitorService.updateById(visitor);
        // 如果未打印过凭证发送人员新增信息
        reactor.notify(EventTopic.VISITOR_DEVICE_ADD, Event.wrap(visitor.getId()));
        visitor.setQrStr(qrStr);
        return visitor;
    }

    public Visitor mackCard(Long visitorId, String icCard) {
        Visitor visitor = visitorService.getById(visitorId);
        if (visitor==null){
            throw new ServiceException(500,"访客不存在");
        }
        if (StringUtils.isBlank(icCard)) {
            throw new ServiceException(500, "卡号不能为空!");
        }
        if (StringUtils.isNotBlank(visitor.getIcCard())) {
            throw new ServiceException(500, "不可二次制卡 请重新发起申请!");
        }
        if (!ObjectUtil.equal(visitor.getStatus(), VisitorConstant.EXAMINATION_PASSD)) {
            throw new ServiceException(500, "未通过审批不可制卡!");
        }
        if (this.existsVisitorCard(icCard)) {
            throw new ServiceException(500, "卡片已经发放给其他访客!");
        }
        if (StringUtils.isNoneBlank(icCard)) {
            visitor.setIcCard(icCard);
            visitor.setIssuanceOfVouchers(0);
            visitorService.updateById(visitor);
            reactor.notify(EventTopic.VISITOR_DEVICE_ADD, Event.wrap(visitor.getId()));
        }
        return visitor;
    }


    public Visitor save(VisitorApiSaveVO visitorApiVO) {
        SysOrg visitor_group = sysOrgService.getOne(new LambdaQueryWrapper<SysOrg>().eq(SysOrg::getCode, BaseConstant.VISITOR_DEVICE_GROUP));
        if (visitor_group == null) {
            throw new ServiceException(500, "访客组不存在");
        }
        Visitor visitor = new Visitor();
        BeanUtils.copyProperties(visitorApiVO, visitor);
        if (visitorApiVO.getInviterId() != null) {
            MemberUser memberUser = memberUserService.getById(visitorApiVO.getInviterId());
            if (memberUser != null) {
                visitor.setInviterName(memberUser.getName());
            }
        }
        if (visitorApiVO.getCompanyId() != null) {
            SysOrg sysOrg = sysOrgService.getById(visitorApiVO.getCompanyId());
            if (sysOrg != null) {
                visitor.setCompanyName(sysOrg.getName());
            }
        }
        // 3 代表访客机
        visitor.setSource(3);
        visitor.setIssuanceOfVouchers(1);
        visitor.setOrgId(visitor_group.getId());
        // 默认审批通过状态
        // 默认未审批状态
        visitor.setStatus(VisitorConstant.NOT_APPROVED);
        visitorService.save(visitor);
        return visitor;
    }

    public void heartBeat(Long deviceId) {
        DeviceBase byId = deviceBaseService.getById(deviceId);
        if (byId == null) {
            throw new ServiceException(500, "找不到设备！");
        }
        byId.setLastOnlineTime(new Date());
        byId.setDeviceState("1");
        deviceBaseService.updateById(byId);
        devicePublisher.publishEvent(DeviceChangeTypeEnum.EDIT, DeviceSourceEnum.BASE,byId);

    }

    public Map<String, Object> getDeviceConfig(String ip, String port, String serverIp, String serverPort, String deviceNo) {
        DeviceBase deviceBase = deviceBaseService.getOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, deviceNo));
        if (deviceBase == null) {
            throw new ServiceException(500, "找不到设备序列号！");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("uploadFeaturePath", "http://" + serverIp + ":" + serverPort + "/deviceApi/v2.0/uploadFeature");
        map.put("uploadRecordPath", "http://" + serverIp + ":" + serverPort + "/deviceApi/v2.0/reportData");
        map.put("uploadRealTimeRecordPath", "");
        map.put("uploadChildRecordPath", "http://" + serverIp + ":" + serverPort + "/deviceApi/v2.0/uploadChildRecord");
        map.put("uploadPersonVerificationRecordPath", "http://" + serverIp + ":" + serverPort + "/deviceApi/v2.0/uploadIdCardRecord");
        map.put("reportHealthData", "http://" + serverIp + ":" + serverPort + "/deviceApi/v2.0/reportHealthData");
        map.put("getTimePath", "http://" + serverIp + ":" + serverPort + "/deviceApi/v2.0/getCurrentTime");
        map.put("deviceName", deviceBase.getName());
        map.put("deviceId", deviceBase.getId());
        map.put("key", "ABCD1234");
        String pagePort = ConstantContextHolder.getSysConfig("PAGE_PORT", String.class, true);
        map.put("baseUrl", MessageFormat.format(DeviceConstant.BASE_URL, serverIp, serverPort));
        map.put("imageUrl", MessageFormat.format(DeviceConstant.BASE_URL, serverIp, pagePort));
        List<SysFileInfo> sysFileInfos = sysFileInfoService.list(new LambdaQueryWrapper<SysFileInfo>().eq(SysFileInfo::getFileOriginName, "小程序二维码.jpg").orderByDesc(SysFileInfo::getCreateTime));
        if (CollectionUtil.isNotEmpty(sysFileInfos)) {
            map.put("miniappQrCode", "/localImage/" + sysFileInfos.get(0).getFileObjectName());
        } else {
            map.put("miniappQrCode", "");
        }
        // 审批状态
        String approval = ConstantContextHolder.getApprovalVisitorDevice();
        map.put("approved", ObjectUtil.equal("NO", approval) ? "0" : "1");
        deviceBase.setCabinetPort(port);
        deviceBase.setCabinetIp(ip);
        deviceBaseService.updateById(deviceBase);

        DwDeviceSet deviceSet = dwDeviceSetService.getOne(new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceBaseId, deviceBase.getId()));
        if (deviceSet == null) {
            DwDeviceSetParam dwDeviceSetParam = new DwDeviceSetParam();
            dwDeviceSetParam.setDeviceBaseId(deviceBase.getId());
            dwDeviceSetParam.setSeverIp(serverIp);
            dwDeviceSetParam.setSeverPort(serverPort);
            dwDeviceSetParam.setIp(ip);
            dwDeviceSetParam.setCabinetPort(port);
            dwDeviceSetService.add(dwDeviceSetParam);
        } else {
            deviceSet.setDeviceBaseId(deviceBase.getId());
            deviceSet.setSeverIp(serverIp);
            deviceSet.setSeverPort(serverPort);
            deviceSet.setIp(ip);
            deviceSet.setCabinetPort(port);
            dwDeviceSetService.updateById(deviceSet);
        }
        return map;
    }


    public Long login(String serialNumber, String passWord) {
        DeviceBase one = deviceBaseService.getOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, serialNumber));
        if (one == null) {
            throw new ServiceException(404, "不存在该设备！");
        }
        if (!ObjectUtil.equal(one.getDevicePassword(), passWord)) {
            throw new ServiceException(500, "密码错误!");
        }

        return one.getId();
    }

    public List<MemberUserPageVO> memberList(String name, String phone, Long orgId) {
        return userMapper.findList(new MemberUserParam().setTel(phone).setName(name).setOrgId(orgId));
//        return memberUserService.list(new LambdaQueryWrapper<MemberUser>()
//                .like(StringUtils.isNotBlank(name), MemberUser::getName, name)
//                .like(StringUtils.isNotBlank(phone), MemberUser::getTel, phone)
//                .eq(MemberUser::getOrgId, orgId).last(" limit 100"));
    }

    public List<SysOrg> orgList(String name) {
        return sysOrgService.list(new LambdaQueryWrapper<SysOrg>()
                .like(StringUtils.isNotBlank(name), SysOrg::getName, name)
                .eq(SysOrg::getType, 1)
                .eq(SysOrg::getStatus, 0)
                        .eq(SysOrg::getShowInMiniApp,1)
                .ne(SysOrg::getCode, "member_group").orderByAsc(SysOrg::getSort));
    }

    public void leave(Boolean all, Long visitorId) {
        List<Long> visitIds = getVisitorIds(all, visitorId);
        if (CollectionUtils.isEmpty(visitIds)) {
            log.error("不存在需要清空的访客！");
            return;
        }
        // 通知设备做新增访客处理
        reactor.notify(EventTopic.VISITOR_DEVICE_DELETE, Event.wrap(visitIds));
        // 修改访客 为已经离场
        visitorService.update(new LambdaUpdateWrapper<Visitor>().set(Visitor::getStatus, 4).set(Visitor::getLeaveTime, new Date()).in(Visitor::getId, visitIds));
    }

    @NotNull
    private List<Long> getVisitorIds(Boolean all, Long visitorId) {
        List<Long> visitIds = new ArrayList<>();
        if (all) {
            // 清退访客
            List<Visitor> visitors = visitorService.list(new LambdaQueryWrapper<Visitor>()
                    .eq(Visitor::getIssuanceOfVouchers, 0)
                    .eq(Visitor::getSource, 3));
            visitIds.addAll(visitors.stream().map(Visitor::getId).collect(Collectors.toList()));
        } else {
            visitIds.add(visitorId);
        }
        return visitIds;
    }

    public VisitorDeviceCountVO count(Long visitorDeviceId) {
        VisitorDeviceCountVO visitorDeviceCountVO = new VisitorDeviceCountVO();
        Date beginTime = DateUtil.beginOfDay(Calendar.getInstance()).getTime();
        Date endTime = DateUtil.endOfDay(Calendar.getInstance()).getTime();
        long oneDayCount = visitorService.count(new LambdaQueryWrapper<Visitor>()
                .eq(Visitor::getIssuanceOfVouchers, 0)
//                .eq(Visitor::getVisitorDeviceId, visitorDeviceId)
                .between(Visitor::getCreateTime, beginTime, endTime)
                .eq(Visitor::getSource, 3));

        long leaveCount = visitorService.count(
                new LambdaQueryWrapper<Visitor>().between(Visitor::getCreateTime, beginTime, endTime)
                        .eq(Visitor::getStatus, 4));
//                        .eq(Visitor::getSource, 3).eq(Visitor::getVisitorDeviceId,visitorDeviceId));
        visitorDeviceCountVO.setVisitorOneDayNum(oneDayCount);
        visitorDeviceCountVO.setLeaveNum(leaveCount);
        visitorDeviceCountVO.setNotLeaveNum(oneDayCount - leaveCount);
        return visitorDeviceCountVO;
    }

    public PageResult<Visitor> findPage(VisitorQueryVO visitorQueryVO) {
        long l = System.currentTimeMillis();

        LambdaQueryWrapper<Visitor> queryWrapper = new LambdaQueryWrapper<Visitor>()
                .eq(Visitor::getSource, 3)
//                .eq(Visitor::getVisitorDeviceId, visitorQueryVO.getVisitorDeviceId())
                .eq(Visitor::getIssuanceOfVouchers, 0)
                .between(ObjectUtil.isAllNotEmpty(visitorQueryVO.getStartTime(), visitorQueryVO.getEndTime()),
                        Visitor::getCreateTime, visitorQueryVO.getStartTime(), visitorQueryVO.getEndTime());
        if (ObjectUtil.isNotNull(visitorQueryVO.getIsLeave())) {
            // 已经离场
            if (visitorQueryVO.getIsLeave()) {
                queryWrapper.eq(Visitor::getStatus, 4);
            }
            // 未离场
            if (!visitorQueryVO.getIsLeave()) {
                queryWrapper.ne(Visitor::getStatus, 4);
            }
        }
        queryWrapper.orderByDesc(Visitor::getCreateTime);
        Page<Visitor> page = visitorService.page(PageFactory.defaultPage(), queryWrapper);
        System.out.println("耗时==============================" + (System.currentTimeMillis() - l));
        return new PageResult<>(page);
    }

}
